﻿#region Copyright

//--------------------------------------------------------------------------------------------------------
// <copyright file="TopicBO.cs" company="DNN Corp®">
//      DNN Corp® - http://www.dnnsoftware.com Copyright (c) 2002-2013 by DNN Corp®
//
//      Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
//      associated documentation files (the "Software"), to deal in the Software without restriction,
//      including without limitation the rights to use, copy, modify, merge, publish, distribute,
//      sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
//      furnished to do so, subject to the following conditions:
//
//      The above copyright notice and this permission notice shall be included in all copies or
//      substantial portions of the Software.
//
//      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
//      NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//      NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
//      DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//      OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
////------------------------------------------------------------------------------------------------------

#endregion Copyright

using DotNetNuke.Entities.Users;
using DotNetNuke.Wiki.BusinessObjects.Models;
using DotNetNuke.Wiki.Utilities;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;

namespace DotNetNuke.Wiki.BusinessObjects
{
    /// <summary>
    /// The Topic Business Object
    /// </summary>
    public class TopicBO : _AbstractBusinessObject<Topic, int>
    {
        #region Variables

        private UnitOfWork mUnitOfWork;

        #endregion Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="TopicBO"/> class.
        /// </summary>
        /// <param name="uOw">The Unit Of Work.</param>
        public TopicBO(UnitOfWork uOw)
            : base(uOw.Context)
        {
            this.mUnitOfWork = uOw;
        }

        #endregion Constructor

        #region Enums

        /// <summary>
        /// The possible controlled errors generated by this class
        /// </summary>
        public enum TopicError
        {
            /// <summary>
            /// The duplicate name
            /// </summary>
            DUPLICATENAME = 1
        }

        #endregion Enums

        #region Methods

        /// <summary>
        /// Gets all by module changed when.
        /// </summary>
        /// <param name="moduleId">The module unique identifier.</param>
        /// <param name="daysBack">The days back.</param>
        /// <returns>SQL Dataset</returns>
        internal IEnumerable<Topic> GetAllByModuleChangedWhen(int moduleId, int daysBack)
        {
            return this.DatabaseContext.ExecuteQuery<Topic>(CommandType.StoredProcedure, string.Concat(this.DataBaseOwner, this.ObjectQualifier, "Wiki_TopicGetAllByModuleChangedWhen"), moduleId, daysBack);
        }

        /// <summary>
        /// Gets a topic associated to the module id and have the passed name
        /// </summary>
        /// <param name="moduleId">the module id the topics are associated to</param>
        /// <param name="name">the topic name</param>
        /// <returns>returns a Topic</returns>
        internal Topic GetByNameForModule(int moduleId, string name)
        {
            return this.DatabaseContext.ExecuteQuery<Topic>(CommandType.StoredProcedure, string.Concat(this.DataBaseOwner, this.ObjectQualifier, "Wiki_TopicGetByNameForModule"), moduleId, name).FirstOrDefault();
        }

        /// <summary>
        /// Gets all topics associated to the module id
        /// </summary>
        /// <param name="moduleId">the module id the topics are associated to</param>
        /// <returns>returns collection of Topics</returns>
        internal IEnumerable<Topic> GetAllByModuleID(int moduleId)
        {
            return this.DatabaseContext.ExecuteQuery<Topic>(CommandType.StoredProcedure, string.Concat(this.DataBaseOwner, this.ObjectQualifier, "Wiki_TopicGetAllByModuleID"), moduleId);
        }

        /// <summary>
        /// Entity_s the evaluate SQL exception.
        /// </summary>
        /// <param name="exc">The exception.</param>
        /// <param name="crudOperation">The crud operation.</param>
        /// <exception cref="System.NotImplementedException">SQL Exception</exception>
        internal override void Entity_EvaluateSqlException(
                    SqlException exc,
                    SharedEnum.CrudOperation crudOperation)
        {
            throw new System.NotImplementedException();
        }

        /// <summary>
        /// Searches the wiki.
        /// </summary>
        /// <param name="searchString">The search string.</param>
        /// <param name="moduleId">The module unique identifier.</param>
        /// <returns>SQL SQL Dataset</returns>
        internal IEnumerable<Topic> SearchWiki(string searchString, int moduleId)
        {
            return this.DatabaseContext.ExecuteQuery<Topic>(CommandType.StoredProcedure, string.Concat(this.DataBaseOwner, this.ObjectQualifier, "Wiki_TopicSearchWiki"), searchString, moduleId);
        }

        /// <summary>
        /// Repositories the delete.
        /// </summary>
        /// <param name="entity">The entity.</param>
        internal override void RepositoryDelete(ref Topic entity)
        {
            this.DatabaseContext.Execute(CommandType.StoredProcedure, string.Concat(this.DataBaseOwner, this.ObjectQualifier, "Wiki_TopicDelete"), entity.TopicID);
        }

        /// <summary>
        /// Gets the notification emails.
        /// </summary>
        /// <param name="topic">The topic.</param>
        /// <returns>A List of Users</returns>
        public List<string> GetNotificationEmails(Topic topic)
        {
            Setting wikiSettings = new SettingBO(this.mUnitOfWork).GetByModuleID(topic.ModuleId);

            List<string> lstUsers = new List<string>();

            if (wikiSettings != null)
            {
                // Gather the email address from the roles assigned to this module...
                if (!string.IsNullOrWhiteSpace(wikiSettings.CommentNotifyRoles))
                {
                    DotNetNuke.Security.Roles.RoleController objRoles = new DotNetNuke.Security.Roles.RoleController();
                    DotNetNuke.Entities.Modules.ModuleController objModules = new DotNetNuke.Entities.Modules.ModuleController();
                    DotNetNuke.Entities.Modules.ModuleInfo objModule = objModules.GetModule(topic.ModuleId);

                    if (objModule != null)
                    {
                        bool fetchUsingDNNRoles = false;
                        bool fetchUsingCustomRoles = false;
                        bool fetchViewUsers = false;
                        bool fetchEditUsers = false;

                        fetchUsingDNNRoles = !string.IsNullOrWhiteSpace(wikiSettings.ContentEditorRoles) && wikiSettings.ContentEditorRoles.StartsWith("UseDNNSettings;");
                        fetchUsingCustomRoles = !string.IsNullOrWhiteSpace(wikiSettings.CommentNotifyRoles) && !wikiSettings.CommentNotifyRoles.StartsWith("UseDNNSettings;");

                        if (!fetchUsingCustomRoles)
                        {
                            fetchEditUsers = wikiSettings.CommentNotifyRoles.Contains(";Edit");
                            fetchViewUsers = wikiSettings.CommentNotifyRoles.Contains(";View");
                        }

                        // Compile our view users, only if enabled
                        if (fetchViewUsers)
                        {
                            foreach (string role in objModule.AuthorizedViewRoles.Trim(new char[] { ';' }).Split(new char[] { ';' }))
                            {
                                if (role.ToLower().Equals("all users"))
                                {
                                    // Trap against fake roles
                                    var arrUsers =
                                        DotNetNuke.Entities.Users.UserController.GetUsers(DotNetNuke.Entities.Portals.PortalController.GetCurrentPortalSettings().PortalId).OfType<UserInfo>();
                                    foreach (DotNetNuke.Entities.Users.UserInfo objUser in arrUsers)
                                    {
                                        if (!lstUsers.Contains(objUser.Email))
                                        {
                                            lstUsers.Add(objUser.Email);
                                        }
                                    }
                                }
                                else
                                {
                                    // This role should be legit
                                    foreach (DotNetNuke.Entities.Users.UserRoleInfo objUserRole in
                                        objRoles.GetUserRolesByRoleName(objModule.PortalID, role))
                                    {
                                        if (!lstUsers.Contains(objUserRole.Email))
                                        {
                                            lstUsers.Add(objUserRole.Email);
                                        }
                                    }
                                }
                            }
                        }

                        // Compile our edit users, only if enabled
                        if (fetchEditUsers)
                        {
                            if (fetchUsingDNNRoles)
                            {
                                // Fetch using dnn edit roles
                                foreach (string role in objModule.AuthorizedEditRoles.Trim(new char[] { ';' }).Split(new char[] { ';' }))
                                {
                                    if (role.ToLower().Equals("all users"))
                                    {
                                        // Trap against fake roles
                                    }
                                    else
                                    {
                                        // This role should be legit
                                        foreach (DotNetNuke.Entities.Users.UserRoleInfo objUserRole in objRoles.GetUserRolesByRoleName(objModule.PortalID, role))
                                        {
                                            if (!lstUsers.Contains(objUserRole.Email))
                                            {
                                                lstUsers.Add(objUserRole.Email);
                                            }
                                        }
                                    }
                                }
                            }
                            else
                            {
                                // Fetch using custom wiki edit roles
                                foreach (string role in wikiSettings.ContentEditorRoles.Trim(new char[] { ';' }).Split(new char[] { ';' }))
                                {
                                    foreach (DotNetNuke.Entities.Users.UserRoleInfo objUserRole in objRoles.GetUserRolesByRoleName(objModule.PortalID, role))
                                    {
                                        if (!lstUsers.Contains(objUserRole.Email))
                                        {
                                            lstUsers.Add(objUserRole.Email);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                // Gather any users emails address from comments in this topic...
                if (wikiSettings.CommentNotifyUsers == true)
                {
                    IEnumerable<CommentEmails> lstEmails = new CommentBO(this.mUnitOfWork).GetCommentNotifyUsers(topic.TopicID);

                    foreach (CommentEmails objCommentEmail in lstEmails)
                    {
                        if (!lstUsers.Contains(objCommentEmail.Email))
                        {
                            lstUsers.Add(objCommentEmail.Email);
                        }
                    }
                }
            }

            return lstUsers;
        }

        #endregion Methods
    }
}